package com.zb.chat.client;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Set;

/**
 * @author: zhaobin
 * @date: 2024/3/3 15:03
 * @Description:
 */
public class ClientThread implements Runnable{

    /**
     * 选择器
     */
    private Selector selector;

    /**
     * 构造器
     * @param selector
     */
    public ClientThread(Selector selector){
        this.selector = selector;
    }
    @Override
    public void run() {
        try{
            while(selector.select() > 0){
                // 得到选择键集合，并遍历
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                for (SelectionKey sk : selectionKeys) {
                    // 可读状态：表示可以读取服务器端发送的数据了
                    if(sk.isReadable()){
                        // 处理可读时的操作
                        readOperator(selector,sk);
                    }
                }
                // 清理选择键集合：为下次轮询查询做准备
                selectionKeys.clear();
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    /**
     * 可读状态时的处理操作
     * @param selector 选择器
     * @param sk 选择键
     * @throws IOException
     */
    private void readOperator(Selector selector,SelectionKey sk) throws IOException {
        // 1、从选择键SelectionKey获取已经就绪的客户端通道
        SocketChannel sc = (SocketChannel) sk.channel();

        // 2、创建Buffer
        ByteBuffer buf = ByteBuffer.allocate(1024);

        // 3、循环读取客户端消息
        String message = "";
        while(sc.read(buf) > 0){
            // 切换buf读写模式
            // 调用 flip()方法会将 position 设回 0，并将 limit 设置成之前 position 的值：即readLength
            buf.flip();
            message += Charset.forName("utf8").decode(buf);
        }

        // 4、把通道再次注册到选择器，监听可读状态。好像不用再次注册
        sc.register(selector,SelectionKey.OP_READ);

        // 5、输出消息
        if(message.length() > 0){
            System.out.println(message);
        }
    }
}
